package tutor;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.util.glu.GLU.*;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;

public class Tutorial6 extends Game {

    // VBO Vertex ID
    int vboVertexID;
    // VBO Color ID
    int vboColorID;
    
    ShaderProgram shaderProgram;
    
    /**
     * Initialize resources
     */
    public void init()
    {
    	// Create Shader Program
    	shaderProgram = new ShaderProgram();
    	shaderProgram.attachVertexShader("tutor/shader.vert");
    	shaderProgram.attachFragmentShader("tutor/shader.frag");

    	// Link the program
    	shaderProgram.link();
    	
    	
        Display.setTitle("3d test 2");
        
        // Initialize OpenGL
        glMatrixMode(GL_PROJECTION);
        gluPerspective(70f, HEIGHT / WIDTH, 1f, 1000f);
        glViewport(0, 0, Display.getWidth(), Display.getHeight());
        
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        // Enable Depth Test
        glEnable(GL_DEPTH_TEST);
        
        // Create Pyramid Vertex Buffer
        FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(3*24);
        vertexBuffer.put(new float[]
        {
        	    // Front face
        	    -0.5f, +0.5f, +0.5f,
        	    +0.5f, +0.5f, +0.5f,
        	    -0.5f, -0.5f, +0.5f,
        	    +0.5f, -0.5f, +0.5f,

        	    // Right face
        	    +0.5f, +0.5f, +0.5f,
        	    +0.5f, +0.5f, -0.5f,
        	    +0.5f, -0.5f, +0.5f,
        	    +0.5f, -0.5f, -0.5f,

        	    // Back face
        	    +0.5f, +0.5f, -0.5f,
        	    -0.5f, +0.5f, -0.5f,
        	    +0.5f, -0.5f, -0.5f,
        	    -0.5f, -0.5f, -0.5f,

        	    // Left face
        	    -0.5f, +0.5f, -0.5f,
        	    -0.5f, +0.5f, +0.5f,
        	    -0.5f, -0.5f, -0.5f,
        	    -0.5f, -0.5f, +0.5f,

        	    // Top face
        	    -0.5f, +0.5f, +0.5f,
        	    +0.5f, +0.5f, +0.5f,
        	    -0.5f, +0.5f, -0.5f,
        	    +0.5f, +0.5f, -0.5f,

        	    // Bottom face
        	    -0.5f, -0.5f, +0.5f,
        	    +0.5f, -0.5f, +0.5f,
        	    -0.5f, -0.5f, -0.5f, 
        	    +0.5f, -0.5f, -0.5f
        });
        vertexBuffer.rewind();
        
        // Create Pyramid Color Buffer
        FloatBuffer colorBuffer = BufferUtils.createFloatBuffer(3*24);
        colorBuffer.put(new float[]
        {
            1, 0, 0,
            0, 1, 0,
            0, 0, 1,
            
            1, 1, 1,
            0, 1, 0,
            0, 0, 1,
            
            1, 0, 0,
            0, 1, 0,
            1, 0, 1, 
            
            1, 1, 0,
            0, 1, 1,
            1, 0, 1,
            
            1, 0, 1,
            0, 1, 0,
            1, 0, 1,
            
            1, 0, 0,
            0, 1, 0,
            0, 1, 0,
        });
        colorBuffer.rewind();
        
        // Create Vertex VBO
        vboVertexID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
        glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        
        // Create Color VBO
        vboColorID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vboColorID);
        glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    
    /**
     * Update logic
     */
    public void update(long elapsedTime)
    {
        if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
            end();
    }
    
    /**
     * Render to the screen
     */
    public void render()
    {
    	// Use shader
    	shaderProgram.bind();
    	
        // Clean both color and depth buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Translate into the view
        glTranslatef(0, 0, -2);

        // Rotate on both x and y axes
        glRotatef(2, 2, 2, 0);

        // Enable client states
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        
        // Bind the vertex VBO
        glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
        glVertexPointer(3, GL_FLOAT, 0, 0);

        // Bind the color VBO
        glBindBuffer(GL_ARRAY_BUFFER, vboColorID);
        glColorPointer(3, GL_FLOAT, 0, 0);

        // Draw the cube with triangle strip
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 24);

        // Translate back
        glTranslatef(0, 0, 2);
        
     // Disable shader
        ShaderProgram.unbind();
    }
    
    /**
     * Display resized
     */
    public void resized()
    {
        glViewport(0, 0, Display.getWidth(), Display.getHeight());
    }
    
    /**
     * Dispose resources
     */
    public void dispose()
    {
        glDeleteBuffers(vboVertexID);
        glDeleteBuffers(vboColorID);
        shaderProgram.dispose();
        
    }
    
    public static void main(String[] args)
    {
        new Tutorial6();
    }
}
